package com.dikeleakagedetection.myapplication.ui.login

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import cn.leancloud.AVObject
import cn.leancloud.AVQuery
import com.dikeleakagedetection.myapplication.DikeLeakageDetectionApp
import com.dikeleakagedetection.myapplication.databinding.ActLoginBinding
import com.dikeleakagedetection.myapplication.logic.bmob.UserCloud
import com.dikeleakagedetection.myapplication.logic.dao.AppDatabase
import com.dikeleakagedetection.myapplication.logic.dao.Dot
import com.dikeleakagedetection.myapplication.logic.dao.Tablet
import com.dikeleakagedetection.myapplication.utils.showToast
import io.reactivex.Observer
import io.reactivex.disposables.Disposable
import kotlin.concurrent.thread

class LoginActivity : AppCompatActivity() {

    private val userDao = AppDatabase.getDatabase(DikeLeakageDetectionApp.context).userDao()
    private val tabletDao = AppDatabase.getDatabase(DikeLeakageDetectionApp.context).tabletDao()
    private val dotDao = AppDatabase.getDatabase(DikeLeakageDetectionApp.context).dotDao()

    private lateinit var binding: ActLoginBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActLoginBinding.inflate(layoutInflater)
        setContentView(binding.root)

        initListener()
    }

    private fun initListener() {
        binding.btnLoginActLogin.setOnClickListener {
            val username = binding.etUsernameActLogin.text.toString()
            val password = binding.etPasswordActLogin.text.toString()

            val query = AVQuery<AVObject>("UserCloud")
            query.whereEqualTo("username", username)
            query.firstInBackground.subscribe(object : Observer<AVObject> {
                override fun onSubscribe(d: Disposable) {}

                override fun onNext(res: AVObject) {
                    val resId = res.serverData["id"].toString().toLong()
                    val resUsername = res.serverData["username"].toString()
                    val resPassword = res.serverData["password"].toString()
                    val user = UserCloud(resId, resUsername, resPassword)
                    if (checkAccount(password, user)) {
                        DikeLeakageDetectionApp.user.username = username
                        DikeLeakageDetectionApp.user.password = password
                        DikeLeakageDetectionApp.user.id = user.id
                        thread {
                            userDao.updateUser(DikeLeakageDetectionApp.user)
                        }
                        syncData(resId)
                    }
                }

                override fun onError(e: Throwable) {
                    e.toString().showToast()
                }

                override fun onComplete() {}
            })

        }
    }

    private fun syncData(userId: Long) {
        val tabletList = ArrayList<Tablet>()
        val dotList = ArrayList<Dot>()

        val tabletQuery = AVQuery<AVObject>("TabletCloud")
        tabletQuery.whereEqualTo("userId", userId)
        tabletQuery.findInBackground().subscribe(object : Observer<List<AVObject>> {
            override fun onNext(results: List<AVObject>) {
                for (tabletAVO in results) {
                    val id = tabletAVO.serverData["id"].toString().toLong()
                    val place = tabletAVO.serverData["place"].toString()
                    val date = tabletAVO.serverData["date"].toString()
                    val length = tabletAVO.serverData["length"].toString().toDouble()
                    val width = tabletAVO.serverData["width"].toString().toDouble()
                    val userId = tabletAVO.serverData["userId"].toString().toLong()
                    val tablet = Tablet(place, date, length, width, userId)
                    tablet.id = id
                    tabletList.add(tablet)
                }
            }

            override fun onError(e: Throwable) {
                e.toString().showToast()
            }

            override fun onSubscribe(d: Disposable) {}

            override fun onComplete() {
                thread {
                    for (tablet in tabletList) {
                        if (tabletDao.loadTabletById(tablet.id) != null) {
                            tabletDao.updateTablet(tablet)
                        } else {
                            tabletDao.insertTablet(tablet)
                        }
                    }
                }

                val dotQuery = AVQuery<AVObject>("DotCloud")
                for (tablet in tabletList) {

                    dotQuery.whereEqualTo("tabletId", tablet.id)
                    dotQuery.limit = 1000
                    dotQuery.findInBackground().subscribe(object : Observer<List<AVObject>> {
                        override fun onSubscribe(d: Disposable) {}
                        override fun onNext(results: List<AVObject>) {
                            for (dotAVO in results) {
                                val id = dotAVO.serverData["id"].toString().toLong()
                                val attitudeX = dotAVO.serverData["attitudeX"].toString().toDouble()
                                val attitudeY = dotAVO.serverData["attitudeY"].toString().toDouble()
                                val attitudeZ = dotAVO.serverData["attitudeZ"].toString().toDouble()
                                val magneticX = dotAVO.serverData["magneticX"].toString().toDouble()
                                val magneticY = dotAVO.serverData["magneticY"].toString().toDouble()
                                val magneticZ = dotAVO.serverData["magneticZ"].toString().toDouble()
                                val locationLng = dotAVO.serverData["locationLng"].toString()
                                val locationLat = dotAVO.serverData["locationLat"].toString()
                                val locationAlt = dotAVO.serverData["locationAlt"].toString()
                                val tabletId = dotAVO.serverData["tabletId"].toString().toLong()
                                val dot = Dot(
                                    magneticX,
                                    magneticY,
                                    magneticZ,
                                    attitudeX,
                                    attitudeY,
                                    attitudeZ,
                                    locationLng,
                                    locationLat,
                                    locationAlt,
                                    tabletId
                                )
                                dot.id = id

                                dotList.add(dot)
                            }
                        }

                        override fun onError(e: Throwable) {
                            e.toString().showToast()
                        }

                        override fun onComplete() {
                            thread {
                                for (dot in dotList) {
                                    if (dotDao.loadDotById(dot.id) != null) {
                                        dotDao.updateDot(dot)
                                    } else {
                                        dotDao.insertDot(dot)
                                    }
                                }
                                dotList.clear()
                            }
                        }

                    })
                }
                "测点数据载入成功".showToast()
            }
        })


    }

    private fun checkAccount(password: String, user: UserCloud?): Boolean {
        if (user == null) {
            "无该用户，请联系管理员注册账号".showToast()
            return false
        }

        if (user.password == password) {
            "登陆成功".showToast()
            user.id.toString().showToast()
            return true
        }

        "密码错误，请重新输入密码".showToast()

        return false
    }
}

